#include "drc_core.h"
#include <pybind11/stl.h>
#include <pybind11/eval.h>
#include <pybind11/embed.h>
#include <stdexcept>
#include <filesystem>
#include <iostream>

namespace py = pybind11;
namespace drc {

PythonRule::PythonRule(const std::string& rule_file) {
    py::gil_scoped_acquire acquire;  // 获取GIL
    
    try {
        // 获取规则文件名（不含路径和扩展名）作为规则名
        std::filesystem::path path(rule_file);
        rule_name = path.stem().string();
        
        // 导入规则模块
        rule_module = py::module_::import(rule_name.c_str());
    }
    catch (const py::error_already_set& e) {
        throw std::runtime_error("Failed to load rule file: " + std::string(e.what()));
    }
}

std::vector<DRCViolation> PythonRule::check(const schematic::Schematic& schematic) {
    py::gil_scoped_acquire acquire;  // 获取GIL
    std::vector<DRCViolation> violations;
    
    try {
        // 获取check_rule函数
        if (!py::hasattr(rule_module, "check_rule")) {
            throw std::runtime_error("Rule module does not have check_rule function");
        }
        
        py::object check_func = rule_module.attr("check_rule");
        
        // 直接将C++的Schematic对象转换为Python对象
        py::object py_schematic = py::cast(schematic);
        
        // 调用Python函数
        py::object result = check_func(py_schematic);
        
        // 将Python返回的列表转换为C++对象
        for (const auto& item : result.cast<py::list>()) {
            py::dict violation_dict = item.cast<py::dict>();
            
            DRCViolation violation;
            violation.rule_name = rule_name;
            
            if (violation_dict.contains("message")) {
                violation.message = violation_dict["message"].cast<std::string>();
            }
            if (violation_dict.contains("severity")) {
                violation.severity = violation_dict["severity"].cast<std::string>();
            }
            if (violation_dict.contains("component")) {
                violation.component = violation_dict["component"].cast<schematic::Component>();
            }
            if (violation_dict.contains("net")) {
                violation.net = violation_dict["net"].cast<schematic::Net>();
            }
            
            violations.push_back(violation);
        }
    }
    catch (const py::error_already_set& e) {
        DRCViolation error_violation;
        error_violation.rule_name = rule_name;
        error_violation.message = "Rule execution failed: " + std::string(e.what());
        error_violation.severity = "error";
        violations.push_back(error_violation);
        
        // 打印更详细的错误信息
        std::cerr << "Python error: " << e.what() << std::endl;
        if (e.trace()) {
            std::cerr << "Traceback:\n" << e.trace() << std::endl;
        }
    }
    
    return violations;
}

DRCManager::DRCManager() : guard() {
    // Python解释器已经在guard构造时初始化
    py::gil_scoped_acquire acquire;  // 确保构造函数中持有GIL
}

DRCManager::~DRCManager() {
    py::gil_scoped_acquire acquire;  // 确保析构函数中持有GIL
    rules.clear();  // 清理规则对象
}

void DRCManager::load_rule(const std::string& rule_file) {
    py::gil_scoped_acquire acquire;  // 获取GIL
    
    try {
        // 添加规则目录到Python路径
        std::filesystem::path rule_path(rule_file);
        auto rule_dir = rule_path.parent_path().string();
        
        py::module_ sys = py::module_::import("sys");
        py::list path = sys.attr("path");
        path.append(rule_dir);
        
        // 创建规则对象
        auto rule = std::make_unique<PythonRule>(rule_file);
        rules.push_back(std::move(rule));
    }
    catch (const std::exception& e) {
        throw std::runtime_error("Failed to load rule: " + std::string(e.what()));
    }
}

void DRCManager::load_rules_from_directory(const std::string& directory) {
    for (const auto& entry : std::filesystem::directory_iterator(directory)) {
        if (entry.path().extension() == ".py") {
            load_rule(entry.path().string());
        }
    }
}

std::vector<DRCViolation> DRCManager::run_all_checks(const schematic::Schematic& schematic) {
    py::gil_scoped_acquire acquire;  // 获取GIL
    std::vector<DRCViolation> all_violations;
    
    try {
        for (const auto& rule : rules) {
            auto violations = rule->check(schematic);
            all_violations.insert(all_violations.end(), violations.begin(), violations.end());
        }
    }
    catch (const std::exception& e) {
        std::cerr << "Error in run_all_checks: " << e.what() << std::endl;
    }
    
    return all_violations;
}

std::vector<DRCViolation> DRCManager::run_rule(const std::string& rule_name, 
                                              const schematic::Schematic& schematic) {
    py::gil_scoped_acquire acquire;  // 获取GIL
    
    try {
        for (const auto& rule : rules) {
            if (dynamic_cast<PythonRule*>(rule.get())->rule_name == rule_name) {
                return rule->check(schematic);
            }
        }
    }
    catch (const std::exception& e) {
        std::cerr << "Error in run_rule: " << e.what() << std::endl;
    }
    
    throw std::runtime_error("Rule not found: " + rule_name);
}

} // namespace drc 